const { DataTypes, Op } = require('sequelize');
const sequelize = require('../config/database');
const passwordUtils = require('../utils/password');

// 用户模型定义
const User = sequelize.define('User', {
  // 主键ID
  id: {
    type: DataTypes.BIGINT,
    primaryKey: true,
    autoIncrement: true,
    allowNull: false
  },
  
  // 用户名
  username: {
    type: DataTypes.STRING(50),
    allowNull: false,
    unique: true,
    validate: {
      notEmpty: {
        msg: '用户名不能为空'
      },
      len: {
        args: [3, 50],
        msg: '用户名长度必须在3-50个字符之间'
      }
    }
  },
  
  // 邮箱
  email: {
    type: DataTypes.STRING(100),
    allowNull: false,
    unique: true,
    validate: {
      notEmpty: {
        msg: '邮箱不能为空'
      },
      isEmail: {
        msg: '请输入有效的邮箱地址'
      }
    }
  },
  
  // 密码（加密存储）
  password: {
    type: DataTypes.STRING(100),
    allowNull: false,
    validate: {
      notEmpty: {
        msg: '密码不能为空'
      },
      len: {
        args: [6, 50],
        msg: '密码长度必须在6-50个字符之间'
      }
    }
  },
  
  // 角色（user/admin）
  role: {
    type: DataTypes.ENUM('user', 'admin'),
    allowNull: false,
    defaultValue: 'user'
  },
  
  // 昵称
  nickname: {
    type: DataTypes.STRING(50),
    allowNull: true
  },
  
  // 头像URL
  avatar: {
    type: DataTypes.STRING(255),
    allowNull: true
  },
  
  // 手机字段暂时注释，避免数据库结构不匹配
  // phone: {
  //   type: DataTypes.STRING(20),
  //   allowNull: true,
  //   unique: true
  // },
  
  // 状态
  status: {
    type: DataTypes.TINYINT,
    allowNull: false,
    defaultValue: 1, // 1: 正常, 0: 禁用
    validate: {
      isIn: {
        args: [[0, 1]],
        msg: '状态值无效'
      }
    }
  },
  
  // 最后登录时间
  last_login_at: {
    type: DataTypes.DATE,
    allowNull: true
  },
  
  // 最后登录IP
  last_login_ip: {
    type: DataTypes.STRING(45),
    allowNull: true
  },
  
  // 登录次数
  login_count: {
    type: DataTypes.INTEGER,
    allowNull: true,
    defaultValue: 0
  },
  
  // 登录失败次数
  login_attempts: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0
  },
  
  // 锁定时间
  lock_until: {
    type: DataTypes.DATE,
    allowNull: true
  },
  
  // 创建时间
  createdAt: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: DataTypes.NOW
  },
  
  // 更新时间
  updatedAt: {
    type: DataTypes.DATE,
    allowNull: false,
    defaultValue: DataTypes.NOW
  },
  
  // 删除时间（软删除）
  deletedAt: {
    type: DataTypes.DATE,
    allowNull: true
  },
  
  // 密码重置令牌
  password_reset_token: {
    type: DataTypes.STRING(255),
    allowNull: true
  },
  
  // 密码重置令牌过期时间
  password_reset_expires: {
    type: DataTypes.DATE,
    allowNull: true
  }
}, {
  // 表配置
  tableName: 'users',
  timestamps: true,
  paranoid: true, // 启用软删除
  underscored: true, // 使用下划线命名
  charset: 'utf8mb4',
  collate: 'utf8mb4_unicode_ci'
});

// 密码加密钩子
User.beforeCreate(async (user) => {
  if (user.password) {
    user.password = passwordUtils.hashPassword(user.password);
  }
});

User.beforeUpdate(async (user) => {
  // 如果密码被修改，重新加密
  if (user.changed('password') && user.password) {
    user.password = passwordUtils.hashPassword(user.password);
  }
});

// 实例方法：验证密码
User.prototype.verifyPassword = function(password) {
  return passwordUtils.verifyPassword(password, this.password);
};

// 实例方法：检查是否被锁定
User.prototype.isLocked = function() {
  return this.lock_until && new Date() < this.lock_until;
};

// 实例方法：增加登录失败次数
User.prototype.incrementLoginAttempts = async function() {
  const maxAttempts = 5;
  const lockoutDuration = 30 * 60 * 1000; // 30分钟
  
  this.login_attempts += 1;
  
  // 如果失败次数达到最大值，锁定账户
  if (this.login_attempts >= maxAttempts) {
    this.lock_until = new Date(Date.now() + lockoutDuration);
  }
  
  await this.save();
};

// 实例方法：重置登录失败次数
User.prototype.resetLoginAttempts = async function() {
  this.login_attempts = 0;
  this.lock_until = null;
  this.last_login_at = new Date();
  this.login_count += 1;
  await this.save();
};

// 类方法：根据用户名或邮箱查找用户
User.findByLogin = async function(login) {
  return await this.findOne({
    where: {
      [Op.or]: [
        { username: login },
        { email: login }
      ]
    }
  });
};

// 类方法：根据密码重置令牌查找用户
User.findByPasswordResetToken = async function(token) {
  // 根据auth.js中的配置，密码重置令牌是哈希存储的，需要验证哈希
  const hashedToken = require('../utils/password').hashPassword(token);
  
  return await this.findOne({
    where: {
      password_reset_token: hashedToken,
      password_reset_expires: {
        [Op.gt]: new Date()
      }
    }
  });
};

module.exports = User;

// 导出到全局，方便其他模块使用
global.User = User;